#
# fusion.http.Folder
#
# Copyright 2007 Helsinki Institute for Information Technology
# and the authors.
#
# Authors: Ken Rimey <rimey@hiit.fi>
#

# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

'''
Handle URLs of the form "/collections?/([0-9a-f]{40})/(.+)/".

As a special case, the folder path may also be empty:

    "/collections?/([0-9a-f]{40})/"

Without parameters, GET displays a clickable list of the contents of
the folder.
'''

import web
import simplejson

from fusion.http.util import withdb, format_xml
from fusion.db.exceptions import *

class Folder(object):
    def GET(self, collection, request_path=''):
        input = web.input(output='xhtml', recurse='',
                          last_mark='0', timeout='0.0',
                          keys_only='', values_only='', reverse='')
        if input.output == 'json':
            return self.GET_json(input, collection, request_path)
        elif input.recurse:
            return self.GET_recursive(input, collection, request_path)
        else:
            return self.GET_nonrecursive(input, collection, request_path)

    @withdb
    def GET_json(self, db, input, collection, request_path):
        try:
            last_mark = int(input.last_mark)
            timeout = float(input.timeout)
            block = (timeout > 0)
        except ValueError:
            return web.badrequest()

        try:
            keys = db.keys(collection, request_path,
                           last_mark = last_mark,
                           autoimport = True,
                           block = block,
                           timeout = timeout,
                           reverse = bool(input.reverse))
        except NoSuchCollection:
            return web.notfound()

        def lookup(key):
            return db.get_text(collection, request_path + '/' + key)

        result = {'mark': db.get_last_mark()}
        if input.keys_only:
            result['keys'] = keys
        elif input.values_only:
            result['values'] = [lookup(k) for k in keys]
        else:
            result['data'] = [(k, lookup(k)) for k in keys]

        web.header('Content-Type', 'application/json')
        print simplejson.dumps(result, indent=2, sort_keys=True)

    @withdb
    def GET_recursive(self, db, input, collection, request_path):
        try:
            results = [path for path in db.keys(collection, request_path,
                                                autoimport=True)
                       if path]
        except NoSuchCollection:
            return web.notfound()

        web.header('Content-Type', 'application/xhtml+xml; charset=UTF-8')
        print '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"'
        print '    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
        print '<html xmlns="http://www.w3.org/1999/xhtml">'
        print '<head>%s</head>' % format_xml('title', '/' + request_path)
        print '<body>'

        # The following is to avoid web.py building its output buffer
        # in quadratic time.  :-(
        buffer = ['<li>' + format_xml('a', path, href=path) + '</li>'
                  for path in sorted(results)]
        print '<ul>' + '\n'.join(buffer) + '</ul>'

        print '</body>'
        print '</html>'

    @withdb
    def GET_nonrecursive(self, db, input, collection, request_path):
        results = set()
        try:
            for path in db.keys(collection, request_path, autoimport=True):
                if path:
                    if '/' in path:
                        head = path[:path.index('/')]
                        results.add((head, None))
                    else:
                        value = db.get(collection, request_path + '/' + path)
                        results.add((path, str(len(value))))
        except NoSuchCollection:
            return web.notfound()

        web.header('Content-Type', 'application/xhtml+xml; charset=UTF-8')
        print '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"'
        print '    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
        print '<html xmlns="http://www.w3.org/1999/xhtml">'
        print '<head>%s</head>' % format_xml('title', '/' + request_path)
        print '<body>'

        print '<ul>'
        for path, size in sorted(results):
            if path == '0x':
                text = 'EMPTY'
            else:
                text = path

            print '<li>'
            if size is None:
                print format_xml('a', text + '/', href=path + '/')
            else:
                print format_xml('a', text, href=path)
                print format_xml('span', '(%s)' % size)
            print '</li>'
        print '</ul>'

        print '<em><a href=".?recurse=true">Recursively expand</a></em>'

        print '</body>'
        print '</html>'
